package com.kalua.list.harvester.tesco;

import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.google.common.collect.Sets;
import com.kalua.list.domainmodel.TextIdentifier;
import com.kalua.list.harvester.parser.AbstractContentLinkExtractor;
import com.kalua.list.harvester.parser.ContentLinkExtractor;
import com.obixlabs.commons.util.LockUtil;

public class TescoContentLinkExtractor extends AbstractContentLinkExtractor {

	private static final String TESCO_WEB_ROOT = "http://www.tesco.com";
	
	private TextIdentifier retailerId;
	
	private String productBrowseRoot;
	private String departmentBrowseRoot;
	private String productDetailsRoot;
	
	private Set<String> linksToFollow;
	private Set<String> productLinks;
	private Set<String> metaInformation;
	private Pattern productHrefPattern;

	
	public TescoContentLinkExtractor(TextIdentifier retailerId) {
		super();
		this.retailerId = retailerId;
		this.productBrowseRoot = "http://www.tesco.com/groceries/product/browse/default.aspx";
		this.departmentBrowseRoot = "http://www.tesco.com/groceries/department/default.aspx";
		this.productDetailsRoot = "http://www.tesco.com/groceries/product/details/";
		this.productHrefPattern = Pattern.compile("href=\"/groceries/product/details/(.*?)\"");
	}
	
	@Override
	public ContentLinkExtractor fromPrototype() 
	{ return new TescoContentLinkExtractor(this.retailerId); }

	@Override
	public void compile(String content) {
		LockUtil.acquireWriteLock(getReadWriteLock());	
		this.linksToFollow = Sets.newHashSet();
		this.productLinks = Sets.newHashSet();
		this.metaInformation = Sets.newHashSet();		
		try {			
			extractDepartmentAndProductRelatedLinks(content);			
			extractProductHRefLinksWithoutProtocol(content);
			extractMetaInformation(content);
		} finally { LockUtil.releaseWriteLock(getReadWriteLock()); }
	}
	
	@Override
	public TextIdentifier getRetailerId() { return this.retailerId; }
	
	@Override
	public Set<String> getLinksToFollow() 
	{ return getReadOnlyCopy(this.linksToFollow); }

	@Override
	public Set<String> getProductLinks() 
	{ return getReadOnlyCopy(this.productLinks);}

	@Override
	public Set<String> getMetaSearchInfo() 
	{ return getReadOnlyCopy(this.metaInformation); }
		
	@Override
	public String toString() {
		return "TescoContentLinkExtractor [" + retailerId
					+ "] toFollow (" + linksToFollow.size() + "), productLinks("
					+ productLinks.size() + "), metaInformation (" 
					+ metaInformation.size() + ")";
	}

	private boolean isCandidateProductLink(String link) 
	{ return link.startsWith(this.productDetailsRoot); }

	private Set<String> getProductLinks(String prefix, String content) {
		Set<String> result = Sets.newHashSet();		
		Matcher matcher = this.productHrefPattern.matcher(content);
		String sublink;
		int firstQuoteIndex=0;
		while (matcher.find()) {
			sublink = matcher.group();
			firstQuoteIndex = sublink.indexOf("\"") + 1;
			if (firstQuoteIndex < sublink.length()) {
				sublink = sublink.substring(firstQuoteIndex, sublink.lastIndexOf("\""));
				result.add(prefix + sublink);
			}
		}
		return result;
	}

	private void extractMetaInformation(String content) {
		String title = getPageTitle(content);		
		if (!StringUtils.isEmpty(title)) {
			title = title.replaceAll("</span>","");
			title = title.replaceAll("<span class=\"(.*?)\">", "");
			String seperator;
			if (title.indexOf("|") > 0 )
				seperator = "|";
			else if (title.indexOf("-") > 0)
				seperator="-";
			else seperator = null;
			
			if (seperator!=null) {
				String[] parts = title.split(seperator);
				for (String part : parts) {
					if (!StringUtils.isEmpty(part))
						this.metaInformation.add(part.trim());
				}
			}
		}
	}

	private void extractDepartmentAndProductRelatedLinks(String content) {
		Set<String> allOutgoingLinks = getOutgoingLinks(content);
		for (String link : allOutgoingLinks) {
			if (isCandidateProductLink(link))
				this.productLinks.add(scrubLink(link, true));
			else if (link.startsWith(this.departmentBrowseRoot) || 
						link.startsWith(this.productBrowseRoot))
				this.linksToFollow.add(scrubLink(link,false));
		}
	}

	private void extractProductHRefLinksWithoutProtocol(String content) {
		Set<String> possibleProductSublinks = 
					getProductLinks(TESCO_WEB_ROOT, content);
		for (String link : possibleProductSublinks) {
			if (isCandidateProductLink(link))
				this.productLinks.add(scrubLink(link, true));				
		}
	}

	private String scrubLink(String link, boolean isProduct) {
		String result;
		int breakerIndex = -1;
		breakerIndex = link.indexOf("#");
		if (breakerIndex < 0) {
			if (isProduct)
				breakerIndex = link.indexOf("&");
			else breakerIndex = link.indexOf("&amp;");
		}
		
		if (breakerIndex >=0)
			result = link.substring(0, breakerIndex);
		else result = link;
		
		return result;
	}
}